﻿using wwl.Contract.Interfaces.Security;
using wwl.Domain.Entities.Rbac;

namespace wwl.Application.Services
{
  /// <summary>
  /// 密码服务（应用层服务）
  /// 实现与密码相关的领域行为，保持Domain层的纯洁性
  /// </summary>
  public class PasswordService
  {
    private readonly IHasher _hasher;

    public PasswordService(IHasher hasher)
    {
      _hasher = hasher;
    }

    /// <summary>
    /// 设置用户密码（包含强度校验和哈希处理）
    /// </summary>
    /// <param name="user">用户实体</param>
    /// <param name="plainPassword">明文密码</param>
    /// <param name="requiredStrength">要求的最低密码强度</param>
    public void SetUserPassword(User user, string plainPassword,
        PasswordStrength requiredStrength = PasswordStrength.Medium)
    {
      if (string.IsNullOrWhiteSpace(plainPassword))
        throw new ArgumentException("密码不能为空", nameof(plainPassword));

      // 检查密码强度
      var strength = _hasher.CheckPasswordStrength(plainPassword);
      if (strength < requiredStrength)
      {
        throw new InvalidOperationException($"密码强度不足，要求至少{requiredStrength}级别，当前为{strength}级别");
      }

      // 使用哈希器生成密码哈希
      user.PasswordHash = _hasher.HashPassword(plainPassword);
    }

    /// <summary>
    /// 验证用户密码
    /// </summary>
    /// <param name="user">用户实体</param>
    /// <param name="plainPassword">待验证的明文密码</param>
    /// <returns>验证成功返回true，否则返回false</returns>
    public bool VerifyUserPassword(User user, string plainPassword)
    {
      if (string.IsNullOrWhiteSpace(plainPassword))
        return false;

      if (string.IsNullOrEmpty(user.PasswordHash))
        return false;

      return _hasher.VerifyPassword(plainPassword, user.PasswordHash);
    }

    /// <summary>
    /// 检查密码是否需要重新哈希（当算法升级时）
    /// </summary>
    /// <param name="user">用户实体</param>
    /// <returns>需要重新哈希返回true，否则返回false</returns>
    public bool NeedsPasswordRehash(User user)
    {
      // 这里可以添加逻辑检查哈希算法版本
      // 目前BCrypt会自动处理，此方法为未来扩展预留
      return false;
    }

    /// <summary>
    /// 验证密码是否符合策略
    /// </summary>
    /// <param name="password">密码</param>
    /// <param name="requiredStrength">要求强度</param>
    /// <returns>是否符合策略</returns>
    public bool ValidatePasswordPolicy(string password, PasswordStrength requiredStrength = PasswordStrength.Medium)
    {
      var strength = _hasher.CheckPasswordStrength(password);
      return strength >= requiredStrength;
    }
  }
}